/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package firstProject;

import framework.Action;
import framework.Percept;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.jgrapht.alg.DijkstraShortestPath;
import vacuumAgent.VAAction;
import vacuumAgent.VAAgent;
import vacuumAgent.VAFloor;
import vacuumAgent.VAPercept;
import vacuumAgent.VATile.VATileStatus;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleDirectedWeightedGraph;
import vacuumAgent.VAConvertToGraph;

/**
 *
 * @author asculx
 */
public class FirstAgent extends VAAgent {

    public static final int MOORE = 9;
    SimpleDirectedWeightedGraph<Point, DefaultWeightedEdge> grafo = null;
    Point originalPosition = null;
    Point currentPosition = null;
    Point currentDest = null;
    VAFloor globalFloor = null;
    List<Point> path = new ArrayList<Point>();
    List<Polvere> posPolvere = null;
    boolean reached = true;

    public FirstAgent(int energy) {
        super(energy);
        posPolvere = new ArrayList<Polvere>();
    }

    private int sumVicine(Point p, VAFloor floor) {
        int count = 0;

        for (int i = (int) p.y - 1; i < (int) p.y + 2; i++) {
            for (int j = (int) p.x - 1; j < (int) p.x + 2; j++) {
                Point pTemp = new Point(j, i);
                if (floor.getTile(pTemp).getStatus() == VATileStatus.DIRTY) {
                    count++;
                }
            }
        }
        return count;
    }

    private void setPolvere(VAFloor floor) {
        posPolvere.clear();
        for (int i = 0; i < floor.getSize(); i++) {
            for (int j = 0; j < floor.getSize(); j++) {
                Point tmp = new Point(i, j);
                if (floor.getTile(tmp).getStatus() == VATileStatus.DIRTY) {
                    int quantity = sumVicine(tmp, floor);
                    System.out.println("CURRENT = "+currentPosition+"  TMP "+tmp);
                    int distance = floor.distanceBetween(currentPosition, tmp);
                    posPolvere.add(new Polvere(tmp, quantity, distance));
                }
            }
        }
    }

    private void computeNextDest(VAPercept percept) {
        VAFloor floor = percept.getFloor();
        setPolvere(floor);
        for (int i = 0; i < posPolvere.size(); i++) {
            Collections.sort(posPolvere);
            
        }

        if (posPolvere.isEmpty()) {
            currentDest = originalPosition;
        } else {
            currentDest = posPolvere.get(0).getPosition();
        }
    }

    private void setOriginalPosition(Point ori) {
        if (this.originalPosition == null) {
            this.originalPosition = new Point(ori);
        }
    }

    private void createGraph(VAPercept p) {
        VAFloor floor = p.getFloor();
        grafo = VAConvertToGraph.toGraph(floor);
    }

    private void setMinPath() {
        List<DefaultWeightedEdge> edgeList = DijkstraShortestPath.findPathBetween(grafo, currentPosition, currentDest);
        int count = 0;
        for (Iterator<DefaultWeightedEdge> it = edgeList.iterator(); it.hasNext();) {
            DefaultWeightedEdge defaultWeightedEdge = it.next();
            path.add(grafo.getEdgeSource(defaultWeightedEdge));
        }
        if (path.size() > 0) {
            path.add(grafo.getEdgeTarget(edgeList.get(edgeList.size() - 1)));
            path.remove(0);
        }


    }

 // UTILIZZATE PER L'ALGOTRITMO

    private void checkPathNeight(VAPercept percept) {
        int x = currentPosition.x;
        int y = currentPosition.y;

        Point p0 = new Point(x - 1, y);
        Point p1 = new Point(x, y - 1);
        Point p2 = new Point(x + 1, y);
        Point p3 = new Point(x, y + 1);
        Point currDST=path.get(0);

        List<Point> tmpList = new LinkedList<Point>();
        boolean setted = false;

//        path.remove(0);

        if (globalFloor.getTile(p0).getStatus() == VATileStatus.DIRTY ) {
            System.out.println("P0");
            tmpList.add(p0);
            tmpList.add(currentPosition);
            
        }
        if (globalFloor.getTile(p1).getStatus() == VATileStatus.DIRTY ) {
            System.out.println("P0");
            tmpList.add(p1);
            tmpList.add(currentPosition);
            
        }
        if (globalFloor.getTile(p2).getStatus() == VATileStatus.DIRTY ) {
            System.out.println("P0");
            tmpList.add(p2);
            tmpList.add(currentPosition);
            
        }
        if (globalFloor.getTile(p3).getStatus() == VATileStatus.DIRTY ) {
            System.out.println("P0");
            tmpList.add(p3);
            tmpList.add(currentPosition);
            setted = true;
        }
        while (!tmpList.isEmpty()) {
            path.add(0, tmpList.remove(tmpList.size()-1));
        }
    }

    private VAAction nextAction(VAPercept percept) {
        VAAction action = new VAAction(VAAction.VAActionType.NOOP);
        if (percept.getCurrentTileStatus() == VATileStatus.DIRTY) {
            action.setActionType(VAAction.VAActionType.SUCK);
            return action;
        }
        System.out.println("$$$$$ BEFORE $$$$$ PATH  = "+path);

        Point tmpDST=null;

        if(!path.isEmpty()){
//            checkPathNeight(percept);
            tmpDST= path.remove(0);
        }else{
            reached=true;
        }
        if(tmpDST!= null ){
            if (tmpDST.x > currentPosition.x) { 
//                action.setActionType(VAAction.VAActionType.MOVENORTH);
                action.setActionType(VAAction.VAActionType.MOVESOUTH);
            } else if (tmpDST.x < currentPosition.x) {
//                action.setActionType(VAAction.VAActionType.MOVESOUTH);
                action.setActionType(VAAction.VAActionType.MOVENORTH);
            } else if (tmpDST.y > currentPosition.y) {
                action.setActionType(VAAction.VAActionType.MOVEEAST);
            } else if (tmpDST.y < currentPosition.y) {
                action.setActionType(VAAction.VAActionType.MOVEWEST);
            }
        }
        return action;
    }

    @Override
    public Action execute(Percept percept) {
        currentPosition = ((VAPercept) percept).getVacuumAgentPosition();
        globalFloor = ((VAPercept) percept).getFloor();
        if (originalPosition == null) {
            setOriginalPosition(currentPosition);
        }

        if(path.isEmpty() && currentPosition.equals(currentDest)){
            reached=true;
        }

        if (reached) {
            System.out.print("CALCOLO LA DESTINAZIONE");
            computeNextDest((VAPercept) percept);

            System.out.println("CREO IL GRAFO");
            createGraph((VAPercept) percept);
            System.out.println("CERCO IL PATH MINIMO");
            setMinPath();

            System.out.println("CURRENT POS = " + currentPosition);
            System.out.println("CURRENT DES = " + currentDest);
            System.out.println("STAMPO IL PATH");
            System.out.println(path);
            System.out.println("");

            System.out.println("VADO AVANTI");
            reached = false;
        }
        VAAction move = nextAction((VAPercept) percept);
        return move;
    }
}

